package com.zl.learning.thread;

import org.junit.Test;

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.LongAccumulator;

public class AskThread implements Runnable {
    CompletableFuture<Integer> re = null;

    public AskThread() {

    }

    public AskThread setRe(CompletableFuture<Integer> re) {
        this.re = re;
        return this;
    }

    @Override
    public void run() {
        int myRe = 0;
        try {
            myRe = re.get() * re.get();
            System.out.println(myRe);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    public static Integer calc(Integer para) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return para * para;
    }

    @Test
    public void test() throws InterruptedException, ExecutionException {
        final CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> calc(50));
        System.out.println(future.get());
    }

    @Test
    public void test0() throws InterruptedException {
        final CompletableFuture<Integer> future = new CompletableFuture<>();
        new Thread(new AskThread().setRe(future)).start();
        Thread.sleep(1000);
        future.complete(60);
    }

    @Test
    public void test1() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> fu = CompletableFuture.supplyAsync(() -> calc(50))
                .thenApply((i) -> Integer.toString(i))
                .thenApply((str) -> "\"" + str + "\"")
                .thenAccept(System.out::println);
        fu.get();
    }

    public static Integer calc2(Integer para) {
        return para / 0;
    }

    @Test
    public void test2() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> fu = CompletableFuture.supplyAsync(() -> calc2(50))
                .exceptionally(ex -> {
                    System.out.println(ex.toString());
                    return 0;
                })
                .thenApply((i) -> Integer.toString(i))
                .thenApply((str) -> "\"" + str + "\"")
                .thenAccept(System.out::println);
        fu.get();
    }

    @Test
    public void test3() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> fu = CompletableFuture.supplyAsync(() -> calc(50))
                .thenCompose(i -> CompletableFuture.supplyAsync(() -> calc(i)))
                .thenApply(str -> String.format("\"%s\"", str))
                .thenAccept(System.out::println);
        fu.get();
    }

    @Test
    public void test4() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> intFuture = CompletableFuture.supplyAsync(() -> calc(50));
        CompletableFuture<Integer> intFuture2 = CompletableFuture.supplyAsync(() -> calc(25));
        CompletableFuture<Void> fu = intFuture.thenCombine(intFuture2, (i, j) -> (i + j))
                .thenApply(str -> "\"" + str + "\"")
                .thenAccept(System.out::println);
        fu.get();
    }

    @Test
    public void test7(){

    }

    @Test
    public void test6() throws InterruptedException {
        LongAccumulator accumulator = new LongAccumulator(Long::max,Long.MIN_VALUE);
        Thread[] ts = new Thread[1000];

        for (int i = 0; i < 1000; i++) {
            ts[i]=new Thread(()->{
                Random random = new Random();
                long value = random.nextLong();
                accumulator.accumulate(value);
            });
            ts[i].start();
        }


        for (int i = 0; i < 1000; i++) {
            ts[i].join();
            System.out.println(accumulator.longValue());
        }
    }
}
